/**
 * 
 */
package cn.ad.server.web.servlet.v2.parser;

import cn.ad.server.web.servlet.v2.requests.GDTImpressionRequest;
import cn.ad.server.web.servlet.v2.requests.TrackingRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 广点通监测请求解析-展示
 * 
 * @author Wu Chengjun
 *
 */
public class GDTImpressionRequestParser extends GDTTrackingRequestParser {

	/**
	 * 广点通解密口令
	 */
	private String token;

	/**
	 * 广点通的ADX 是 将win_price封装在 展示请求中的
	 */
	public static String PARAM_WIN_PRICE = "win_price";

	/*
	 * (non-Javadoc)
	 * 
	 * @see cn.ad.server.web.servlet.v2.parser.
	 * GDTTrackingRequestParser#readTrackingParam(javax.servlet.http.
	 * HttpServletRequest,
	 * cn.falconnect.adserver.adapter.TrackingRequest)
	 */
	@Override
	public void readTrackingParam(HttpServletRequest request, TrackingRequest trackingRequest)
			throws AdRequestParseException {
		super.readTrackingParam(request, trackingRequest);
		try {
			((GDTImpressionRequest) trackingRequest).setWin_price(readWinPrice(request));
		} catch (ParameterParseExcption ex) {
			ex.setResult(trackingRequest);
			throw ex;
		}
	}
	
	//提交审核的时候win_price人为的多了个=号，做下处理
	String fiterWinPrice(String winPrice) {
		if (winPrice.startsWith("="))
			return winPrice.substring(1, winPrice.length());
		return winPrice;
	}

	private double readWinPrice(HttpServletRequest request) throws ParameterParseExcption {
		String winPrice = request.getParameter(PARAM_WIN_PRICE);
		double price = 0.0d;
		if (StringUtils.isNoneEmpty(winPrice) && StringUtils.isNotBlank(winPrice)) {
			try {
				winPrice = fiterWinPrice(winPrice);
				String priceStr = decodePrice(winPrice, getToken().substring(0, 16));
				if (StringUtils.isEmpty(priceStr)) {
					throw new ParameterParseExcption(DefaultWinoticeRequestParser.PARAM_WINOTICE_PRICE, winPrice,
							"解析广点通winprice解析失败.");
				}
				BigDecimal bd = new BigDecimal(Double.valueOf(priceStr));
				price = bd.divide(new BigDecimal(100 * 1000)).doubleValue();
			} catch (InvalidKeyException | UnsupportedEncodingException | NoSuchAlgorithmException
					| NoSuchPaddingException | IllegalBlockSizeException | NumberFormatException
					| BadPaddingException e) {
				throw new ParameterParseExcption(DefaultWinoticeRequestParser.PARAM_WINOTICE_PRICE, winPrice,
						"解析广点通winprice出现异常:" + e.getMessage(), e);
			}
		} else {
			throw new ParameterParseExcption(DefaultWinoticeRequestParser.PARAM_WINOTICE_PRICE, null,
					"解析广点通winprice出现异常");
		}
		return price;
	}

	private String decodePrice(String encoded_price, String token)
			throws InvalidKeyException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException,
            IllegalBlockSizeException, BadPaddingException {
		byte[] after_base64_decode = Base64Decode(encoded_price);
		return AES128Decode(after_base64_decode, token);
	}

	private byte[] Base64Decode(String encoded_price) throws UnsupportedEncodingException {
		return Base64.decodeBase64(encoded_price);
	}

	private String AES128Decode(byte[] encoded_price, String token)
			throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException {
		byte[] raw = token.getBytes("utf-8");
		SecretKeySpec key_spec = new SecretKeySpec(raw, "AES");

		Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
		cipher.init(Cipher.DECRYPT_MODE, key_spec);
		byte[] decoded_price = cipher.doFinal(encoded_price);
		return new String(decoded_price, "utf-8");
	}

	/**
	 * @return the token
	 */
	public String getToken() {
		return token;
	}

	/**
	 * @param token
	 *            the token to set
	 */
	public void setToken(String token) {
		this.token = token;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cn.ad.server.web.servlet.v2.parser.
	 * TrackingRequestParser#createTrackingRequest(javax.servlet.http.
	 * HttpServletRequest)
	 */
	@Override
	public TrackingRequest createTrackingRequest(HttpServletRequest request) throws AdRequestParseException {
		return new GDTImpressionRequest();
	}

}
